Retirado do artigo Miller et al. (2019). Distance sampling in R. Journal of Statistical Sofware 89(1)

paste0(
  here::here(),
  "/data/cutia_tap_arap.csv"
) |> 
  readr::guess_encoding()

Formatação do conjunto de dados

Variáveis necessárias para o data.frame:

Transectos que foram amostrados, mas que não tiveram observações (n = 0) devem ser incluídos no conjunto de dados com NA nas observações de distância e qualquer outra covariael para a qual não se tenha observação.

# cutia_tap_arap |> 
#   complete(Region.Label, Sample.Label, sp_name) |> 
#   datatable(filter = list(position = "top"))

Jogar a imputacao de NAs pra dentro da funcao carregar dados completos.

Determinando a distância para truncar os dados

# desenha o grafico com a distribuicao de distancias perpendiculares
cutia_tap_arap |> 
  plotar_distribuicao_distancia_interativo()
Warning: Continuous y aesthetic
ℹ did you forget `aes(group = ...)`?

Ajustando funções de detecção no R

Cutias da Resex Tapajós-Arapiuns

Half-Normal sem termos de ajuste

Ajustando um modelo ao dados das cutias Dasyprocta croconota, configurando uma distância limite de 20m e usando Half-normal como key function usando o argumento key, sem termo de ajuste.

# ajustando a função de detecção para uma distancia de truncamento de 20 metros
# Key function - Half-normal 
cutia_tap_arap_hn <- cutia_tap_arap |> 
  ds(
    truncation = 20,
    key = "hn",
    adjustment = NULL
  )
Fitting half-normal key function
AIC= 7227.642
Warning: Some observations not included in the analysis

Half-Normal com termos de ajuste Hermite-Polynomial

Ajustando um modelo ao dados das cutias Dasyprocta croconota, configurando uma distância limite de 20m e usando Half-normal como key function usando o argumento key, com termo de ajuste do tipo Hermite-polynomial.

# ajustando a função de detecção para uma distancia de truncamento de 20 metros
# Key function - Half-normal 
cutia_tap_arap_hn_herm <- cutia_tap_arap |> 
  ds(
    truncation = 20,
    key = "hn",
    adjustment = "herm"
  )
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 7227.642
Fitting half-normal key function with Hermite(4) adjustments
AIC= 7229.142

Half-normal key function selected.
Warning: Some observations not included in the analysis

Half-Normal com termos de ajuste Cosine

Ajustando um modelo ao dados das cutias Dasyprocta croconota, configurando uma distância limite de 20m e usando Half-normal como key function usando o argumento key, com termo de ajuste do tipo Cosine.

# ajustando a função de detecção para uma distancia de truncamento de 20 metros
# Key function - Half-normal 
cutia_tap_arap_hn_cos <- cutia_tap_arap |> 
  ds(
    truncation = 20,
    key = "hn"
    )
Starting AIC adjustment term selection.
Fitting half-normal key function
AIC= 7227.642
Fitting half-normal key function with cosine(2) adjustments
AIC= 7207.469
Fitting half-normal key function with cosine(2,3) adjustments
AIC= 7201.248
Fitting half-normal key function with cosine(2,3,4) adjustments
Warning: Detection function is not strictly monotonic!AIC= 7152.177
Fitting half-normal key function with cosine(2,3,4,5) adjustments
Warning: Detection function is not strictly monotonic!AIC= 7146.681
Fitting half-normal key function with cosine(2,3,4,5,6) adjustments
Warning: Detection function is not strictly monotonic!AIC= 7129.427
Warning: Detection function is not strictly monotonic!Warning: Some observations not included in the analysis

Hazard-Rate sem termos de ajuste

Ajustando um modelo ao dados da cutia Dasyprocta croconota, configurando uma distância limite de 20m e usando Hazard rate como key function usando o argumento key.

# Key function - Hazard-rate 
cutia_tap_arap_hr <- cutia_tap_arap |> 
  ds(
    truncation = 20,
     key = "hr",
    adjustment = NULL
  )
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6907.541
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Some observations not included in the analysis

Hazard-Rate com termos de ajuste Simple-polynomial

Ajustando um modelo ao dados da cutia Dasyprocta croconota, configurando uma distância limite de 20m e usando Hazard rate como key function usando o argumento key e termo de ajuste do tipo polinomial simples.

# Key function - Hazard-rate 
cutia_tap_arap_hr_poly <- cutia_tap_arap |> 
  ds(
    truncation = 20,
     key = "hr",
    adjustment = "poly"
  )
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6907.541
Fitting hazard-rate key function with simple polynomial(4) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Some observations not included in the analysis

Hazard-Rate com termos de ajuste Cosine

Ajustando um modelo ao dados da cutia Dasyprocta croconota, configurando uma distância limite de 20m e usando Hazard rate como key function usando o argumento key e termo de ajuste do tipo cosseno.

# Key function - Hazard-rate 
cutia_tap_arap_hr_cos <- cutia_tap_arap |> 
  ds(
    truncation = 20,
    key = "hr"
    )
Starting AIC adjustment term selection.
Fitting hazard-rate key function
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).AIC= 6907.541
Fitting hazard-rate key function with cosine(2) adjustments
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Model fitting did not converge. Try different initial values or different model
  Model failed to converge.

Hazard-rate key function selected.
Warning: Estimated hazard-rate scale parameter close to 0 (on log scale). Possible problem in data (e.g., spike near zero distance).Warning: Some observations not included in the analysis
plot(cutia_tap_arap_hn, breaks = seq(0, 20, 2.5))

plot(cutia_tap_arap_hn_herm, breaks = seq(0, 20, 2.5))

plot(cutia_tap_arap_hn_cos, breaks = seq(0, 20, 2.5))

plot(cutia_tap_arap_hr, breaks = seq(0, 20, 2.5))

plot(cutia_tap_arap_hr_poly, breaks = seq(0, 20, 2.5))

plot(cutia_tap_arap_hr_cos, breaks = seq(0, 20, 2.5))

Ajustando um modelo ao dados das cutias, configurando uma distância limite de 20m e usando Uniform como key function a séria de ajuste com o argumento adjustment ee especificando a ordem com o argumento order.

cutia_unifcos <- cutia_tap_arap |> 
  ds(truncation = 20,
     key = "unif",
     adjustment = "cos",
     order = c(1, 2))

Ajuste Hermite pollynomial usa od código "herm" e polinomial simples "poly".

Podemos incluir covariáveis utilizando o argumento formula = ~ .... Abaixo, está especificado um modelo “Hazard-rate” para os dados de cutia q ue inclui o tempo de senso como covariável e uma distância limite de 20m.

cutia_hr_time <- cutia_tap_arap_15 |> 
  ds(truncation = 20,
     key = "hr",
     formula = ~ cense_time)

Adicionando uma segunda covariável: tamanho do grupo.

cutia_hr_time_size <- ds(data = cutia_tap_arap_15,
                     truncation = 20,
                     transect = "line",
                     key = "hr",
                     formula = ~ cense_time + size)
plot(cutia_hr_time)
plot(cutia_hr_time_size)

Checagem e seleção de modelos

Podemos usar a função summary para obter informações importantes sobre o modelo.

summary(cutia_hn)

O resultado inclui detalhes sobre o dado e a especificação do modelo, assim como dos coeficientes (\(\beta_{j}\)) e sua inceteza, a média do valor de detectabilidade e sua incerteza e uma estimativa da abundância na área coberta pela amostragem (sem levar em consideração o tamanho dos agrupamentos, ou bandos).

Bondade de ajuste

Para visualizar quão bem a função de detecção se ajusta aos dados quanto temos as distâncias exatas podemos usar um plot de quantis empíricos x teóricos (Q-Q plot). Ele compara a função de distribuição cumulativa (CDF) dos valores ajustados da função detecção a distribuição empírica dos dados (EDF).

Também podemos usar o teste de Cramér-von Mises para testar se os pontos da EDF e da CDF tem origem na mesma distribuição. O teste usa a soma de todas as distâncias entre um ponto e a linha y = x para formar a estatística a ser testada. Um resultado significativo fornece evidência contra a hiipótese nula, sugerindo que o modelo não se ajusta bem aos dados.

# ajustando um modelo Half-normal
cutia_hn <- ds(data = cutia_tap_arap_15,
                 truncation = 20,
                 transect = "line",
                 key = "hn", 
                 adjustment = NULL)

# conduzindo o teste dfe bondadede ajuste de Cramer-von Mises
gof_ds(cutia_hn)

gof_ds(cutia_hr_time)

O resutlado do teste aponta que o modelo Half-normal deve ser descartado.

Testes de bondade de ajuste de chi-quadrado são gerados usando a função gof_ds quando as distâncias forneceidas estão categorizadas.

Seleção de Modelos

Uma vez que temos um conjunto de modelos plausíveis, podemos utilizar o cirtériode informaçãode Akaike (AIC) para selecionar entre os modelos o que melhor se ajusta aos dados utilizando a função summarize_ds_models.

# gerando uma tabela de seleção de modelos usando AIC
summarize_ds_models(cutia_hn, cutia_hr_time, cutia_hr_time_size)

O melhor modelo é o Hazard-rate com tempo de senso e tamanho do grupo como covariáveis.

Estimando a abundância e a variância

Estimando abundância e variância no R

Para obter a abundância na região de estudo, primeiro calculamos a abundância na área amostrada para obter \(N_c\) e em seguida escalonamos esse valor para toda a área de estudo multiplicando \(N_c\) pela razão entre a área amostrada e a área da região. Para estimar a abundância na área amostrada, utilizamos as estimativas de probabilidade de detecção no estimador de Horvitz-Thompson.

Quando fornecemos os dados no formato correto (“flatfile”) ds irá automaticamente calcular as estimativas de abundância baseado nas informações de amostragem presenta nos dados.

summary(cutia_hn)
  1. Summary statistics: fornece as áreas, aŕea de amostragem, esforço, número de observações, número de transectos, taxa de encontro, seus erros padrões e coeficientes de variação para cada estrato;

  2. Abundance: fornece estimativas, erros padrões, coeficientesde variação, intervalos de confiança inferior e superior, graus de liberdade para a estimativa de abundância de cada estrato;

  3. Densidade: lista as mesmas estatísticas de Abundance, só que para densidade.

LS0tCnRpdGxlOiAiRGlzdGFuY2Ugbm8gUiBjb20gZGFkb3MgJ21vZGVsbyciCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClJldGlyYWRvIGRvIGFydGlnbyBNaWxsZXIgZXQgYWwuICgyMDE5KS4gRGlzdGFuY2Ugc2FtcGxpbmcgaW4gUi4gSm91cm5hbCBvZiBTdGF0aXN0aWNhbCBTb2Z3YXJlIDg5KDEpCgpgYGB7ciBzZXR1cH0KIyBpbnN0YWxhciBwYWNvdGVzIG5lY2Vzc8OhcmlvcwojaW5zdGFsbC5wYWNrYWdlcygiRGlzdGFuY2UiKQoKIyBpbnN0YWxhciBwYWNvdGVzIGFkaWNpb25haXMKI2luc3RhbGwucGFja2FnZXMoIm1yZHMiKQojaW5zdGFsbC5wYWNrYWdlcygiZHNtIikKI2luc3RhbGwucGFja2FnZXMoIm1hZHMiKQojaW5zdGFsbC5wYWNrYWdlcygiZHNpbXMiKQoKIyBjYXJyZWdhciBwYWNvdGVzIApsaWJyYXJ5KERpc3RhbmNlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KERUKQpsaWJyYXJ5KGZsZXh0YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KHRpZHlyKQoKIyBjYXJyZWdhciBhcyBmdW7Dp8O1ZXMgZGEgcGFzdGEgUgojIGNhcnJlZ2FyIGZ1bsOnw6NvIHNjcmlwdF9jYXJyZWdhcl9mdW7Dp8O1ZXNfcGFzdGFfci5SCnNvdXJjZSgKICBwYXN0ZTAoCiAgICBoZXJlOjpoZXJlKCksCiAgICAiL1IvbWluaGFzX2Z1bmNvZXMuUiIKICApCikKCiMgY2FycmVnYXIgZGFkb3MKY3V0aWFfdGFwX2FyYXAgPC0gdHJhbnNmb3JtYXJfcGFyYV9kaXN0YW5jZVJfY292YXJpYXZlaXMoKSB8PiAKICBmaWx0ZXIoCiAgICB1Y19uYW1lID09ICJSZXNleCBUYXBham9zLUFyYXBpdW5zIiwKICAgIHNwX25hbWUgPT0gIkRhc3lwcm9jdGEgY3JvY29ub3RhIgogICkgfD4gCiAgZHJvcF9uYShkaXN0YW5jZSkKICAKcmVhZHI6OndyaXRlX2V4Y2VsX2NzdigKICBjdXRpYV90YXBfYXJhcCwKICBwYXN0ZTAoCiAgICBoZXJlOjpoZXJlKCksCiAgICAiL2RhdGEvY3V0aWFfdGFwX2FyYXAuY3N2IgogICksIAopCgpjdXRpYV90YXBfYXJhcCB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9ICJ0b3AiKQpgYGAKCiMgRm9ybWF0YcOnw6NvIGRvIGNvbmp1bnRvIGRlIGRhZG9zCgpWYXJpw6F2ZWlzIG5lY2Vzc8OhcmlhcyBwYXJhIG8gYGRhdGEuZnJhbWVgOgoKLSBgUmVnaW9uLkxhYmVsYDogdmV0b3IgZmF0b3IgY29tIG8gZXN0cmF0byBjb250ZW5kbyBvIHRyYW5zZWN0byAocG9kZSBzZXIgdW1hIGVzdHJhdGlmaWNhw6fDo28gcHLDqS1hbW9zdHJhZ2VtIC0gVUNzIC0gb3UgcMOzcy1hbW9zdHJhZ2VtIC0gZXguIHJlZ2nDo28sIGVzdGFkbywgYmlvbWEpCgotIGBBcmVhYDogdmV0b3IgbnVtw6lyaWNvIGNvbnRlbmRvIGEgw6FyZWEgZG8gZXN0cmF0bzsKCi0gYFNhbXBsZS5MYWJlbGA6IHZldG9yIG7Dum1lcmljbyBjb250ZW5kbyBhIGlkZW50aWRhZGUgKElEKSBkbyB0cmFuc2VjdG8KCi0gYG9iamVjdGA6IG5vbWUgYWRpY2lvbmFsLCB2ZXIgc2XDp8OjbyA2OwoKLSBgZGV0ZWN0ZWRgOiBub21lIGFkaWNpb25hbCwgdmVyIHNlw6fDo28gNjsKCi0gYEVmZm9ydGA6IHZldG9yIG7Dum1lcmljbyBjb250ZW5kbyBvIGVzZm9yw6dvIGRvIHRyYW5zZWN0byAocGFyYSBsaW5oYXMgc2V1IGNvbXByaW1lbnRvLCBwYXJhIHBvbnRvcyBvIG7Dum1lcm8gZGUgdmV6ZXMgcXVlIG8gcG9udG8gZm9pIHZpc2l0YWRvKQoKLSBgc2l6ZWA6IHZldG9yIG51bcOpcmljbyBjb3BudGVuZG8gbyB0YW1hbmhvIGRvIGdydXBvIG9ic2VydmFkbzsKCi0gYGRpc3RhbmNlYDogdmV0b3IgbnVtw6lyaWNvIGRlIGRpc3TDom5jaWFzIG9ic2VydmFkYXM7CgotIGBNb250aGA6CgotIGBPQnNgOgoKLSBgU3BgOgoKIC0gYG1hc2A6CiAKIC0gYEhBU2A6CiAKIC0gYFN0dWR5LkFyZWFgOgogClRyYW5zZWN0b3MgcXVlIGZvcmFtIGFtb3N0cmFkb3MsIG1hcyBxdWUgbsOjbyB0aXZlcmFtIG9ic2VydmHDp8O1ZXMgKG4gPSAwKSBkZXZlbSBzZXIgaW5jbHXDrWRvcyBubyBjb25qdW50byBkZSBkYWRvcyBjb20gYE5BYCBuYXMgb2JzZXJ2YcOnw7VlcyBkZSBkaXN0w6JuY2lhIGUgcXVhbHF1ZXIgb3V0cmEgY292YXJpYWVsIHBhcmEgYSBxdWFsIG7Do28gc2UgdGVuaGEgb2JzZXJ2YcOnw6NvLgogCmBgYHtyfQojIGN1dGlhX3RhcF9hcmFwIHw+IAojICAgY29tcGxldGUoUmVnaW9uLkxhYmVsLCBTYW1wbGUuTGFiZWwsIHNwX25hbWUpIHw+IAojICAgZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKSm9nYXIgYSBpbXB1dGFjYW8gZGUgYE5BYHMgcHJhIGRlbnRybyBkYSBmdW5jYW8gY2FycmVnYXIgZGFkb3MgY29tcGxldG9zLgoKIyMgRGV0ZXJtaW5hbmRvIGEgZGlzdMOibmNpYSBwYXJhIHRydW5jYXIgb3MgZGFkb3MKCmBgYHtyLCBmaWcuaGVpZ2h0PTE1LCBmaWcud2lkdGg9MTAsIHdhcm5pbmc9RkFMU0V9CiMgZGVzZW5oYSBvIGdyYWZpY28gY29tIGEgZGlzdHJpYnVpY2FvIGRlIGRpc3RhbmNpYXMgcGVycGVuZGljdWxhcmVzCmN1dGlhX3RhcF9hcmFwIHw+IAogIHBsb3Rhcl9kaXN0cmlidWljYW9fZGlzdGFuY2lhX2ludGVyYXRpdm8oKQpgYGAKCiAKIyMgQWp1c3RhbmRvIGZ1bsOnw7VlcyBkZSBkZXRlY8Onw6NvIG5vIFIKCiMjIyBDdXRpYXMgZGEgUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMKCiMjIyMgKkhhbGYtTm9ybWFsKiBzZW0gdGVybW9zIGRlIGFqdXN0ZQoKQWp1c3RhbmRvIHVtIG1vZGVsbyBhbyBkYWRvcyBkYXMgY3V0aWFzICpEYXN5cHJvY3RhIGNyb2Nvbm90YSosIGNvbmZpZ3VyYW5kbyB1bWEgZGlzdMOibmNpYSBsaW1pdGUgZGUgMjBtIGUgdXNhbmRvICpIYWxmLW5vcm1hbCogY29tbyAqa2V5IGZ1bmN0aW9uKiB1c2FuZG8gbyBhcmd1bWVudG8gYGtleWAsIHNlbSB0ZXJtbyBkZSBhanVzdGUuCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIHBhcmEgdW1hIGRpc3RhbmNpYSBkZSB0cnVuY2FtZW50byBkZSAyMCBtZXRyb3MKIyBLZXkgZnVuY3Rpb24gLSBIYWxmLW5vcm1hbCAKY3V0aWFfdGFwX2FyYXBfaG4gPC0gY3V0aWFfdGFwX2FyYXAgfD4gCiAgZHMoCiAgICB0cnVuY2F0aW9uID0gMjAsCiAgICBrZXkgPSAiaG4iLAogICAgYWRqdXN0bWVudCA9IE5VTEwKICApCmBgYAoKIyMjIyAqSGFsZi1Ob3JtYWwqIGNvbSB0ZXJtb3MgZGUgYWp1c3RlICpIZXJtaXRlLVBvbHlub21pYWwqCgpBanVzdGFuZG8gdW0gbW9kZWxvIGFvIGRhZG9zIGRhcyBjdXRpYXMgKkRhc3lwcm9jdGEgY3JvY29ub3RhKiwgY29uZmlndXJhbmRvIHVtYSBkaXN0w6JuY2lhIGxpbWl0ZSBkZSAyMG0gZSB1c2FuZG8gKkhhbGYtbm9ybWFsKiBjb21vICprZXkgZnVuY3Rpb24qIHVzYW5kbyBvIGFyZ3VtZW50byBga2V5YCwgY29tIHRlcm1vIGRlIGFqdXN0ZSBkbyB0aXBvICpIZXJtaXRlLXBvbHlub21pYWwqLgoKYGBge3J9CiMgYWp1c3RhbmRvIGEgZnVuw6fDo28gZGUgZGV0ZWPDp8OjbyBwYXJhIHVtYSBkaXN0YW5jaWEgZGUgdHJ1bmNhbWVudG8gZGUgMjAgbWV0cm9zCiMgS2V5IGZ1bmN0aW9uIC0gSGFsZi1ub3JtYWwgCmN1dGlhX3RhcF9hcmFwX2huX2hlcm0gPC0gY3V0aWFfdGFwX2FyYXAgfD4gCiAgZHMoCiAgICB0cnVuY2F0aW9uID0gMjAsCiAgICBrZXkgPSAiaG4iLAogICAgYWRqdXN0bWVudCA9ICJoZXJtIgogICkKYGBgCgojIyMjICpIYWxmLU5vcm1hbCogY29tIHRlcm1vcyBkZSBhanVzdGUgKkNvc2luZSoKCkFqdXN0YW5kbyB1bSBtb2RlbG8gYW8gZGFkb3MgZGFzIGN1dGlhcyAqRGFzeXByb2N0YSBjcm9jb25vdGEqLCBjb25maWd1cmFuZG8gdW1hIGRpc3TDom5jaWEgbGltaXRlIGRlIDIwbSBlIHVzYW5kbyAqSGFsZi1ub3JtYWwqIGNvbW8gKmtleSBmdW5jdGlvbiogdXNhbmRvIG8gYXJndW1lbnRvIGBrZXlgLCBjb20gdGVybW8gZGUgYWp1c3RlIGRvIHRpcG8gKkNvc2luZSouCgpgYGB7cn0KIyBhanVzdGFuZG8gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIHBhcmEgdW1hIGRpc3RhbmNpYSBkZSB0cnVuY2FtZW50byBkZSAyMCBtZXRyb3MKIyBLZXkgZnVuY3Rpb24gLSBIYWxmLW5vcm1hbCAKY3V0aWFfdGFwX2FyYXBfaG5fY29zIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIGRzKAogICAgdHJ1bmNhdGlvbiA9IDIwLAogICAga2V5ID0gImhuIgogICAgKQpgYGAKCiMjIyMgKkhhemFyZC1SYXRlKiBzZW0gdGVybW9zIGRlIGFqdXN0ZQoKQWp1c3RhbmRvIHVtIG1vZGVsbyBhbyBkYWRvcyBkYSBjdXRpYSAqRGFzeXByb2N0YSBjcm9jb25vdGEqLCBjb25maWd1cmFuZG8gdW1hIGRpc3TDom5jaWEgbGltaXRlIGRlIDIwbSBlIHVzYW5kbyAqSGF6YXJkIHJhdGUqIGNvbW8gKmtleSBmdW5jdGlvbiogdXNhbmRvIG8gYXJndW1lbnRvIGBrZXlgLgoKYGBge3J9CiMgS2V5IGZ1bmN0aW9uIC0gSGF6YXJkLXJhdGUgCmN1dGlhX3RhcF9hcmFwX2hyIDwtIGN1dGlhX3RhcF9hcmFwIHw+IAogIGRzKAogICAgdHJ1bmNhdGlvbiA9IDIwLAogICAgIGtleSA9ICJociIsCiAgICBhZGp1c3RtZW50ID0gTlVMTAogICkKYGBgCgojIyMjICpIYXphcmQtUmF0ZSogY29tIHRlcm1vcyBkZSBhanVzdGUgKlNpbXBsZS1wb2x5bm9taWFsKgoKQWp1c3RhbmRvIHVtIG1vZGVsbyBhbyBkYWRvcyBkYSBjdXRpYSAqRGFzeXByb2N0YSBjcm9jb25vdGEqLCBjb25maWd1cmFuZG8gdW1hIGRpc3TDom5jaWEgbGltaXRlIGRlIDIwbSBlIHVzYW5kbyAqSGF6YXJkIHJhdGUqIGNvbW8gKmtleSBmdW5jdGlvbiogdXNhbmRvIG8gYXJndW1lbnRvIGBrZXlgIGUgdGVybW8gZGUgYWp1c3RlIGRvIHRpcG8gcG9saW5vbWlhbCBzaW1wbGVzLgoKYGBge3J9CiMgS2V5IGZ1bmN0aW9uIC0gSGF6YXJkLXJhdGUgCmN1dGlhX3RhcF9hcmFwX2hyX3BvbHkgPC0gY3V0aWFfdGFwX2FyYXAgfD4gCiAgZHMoCiAgICB0cnVuY2F0aW9uID0gMjAsCiAgICAga2V5ID0gImhyIiwKICAgIGFkanVzdG1lbnQgPSAicG9seSIKICApCmBgYAoKIyMjIyAqSGF6YXJkLVJhdGUqIGNvbSB0ZXJtb3MgZGUgYWp1c3RlICpDb3NpbmUqCgpBanVzdGFuZG8gdW0gbW9kZWxvIGFvIGRhZG9zIGRhIGN1dGlhICpEYXN5cHJvY3RhIGNyb2Nvbm90YSosIGNvbmZpZ3VyYW5kbyB1bWEgZGlzdMOibmNpYSBsaW1pdGUgZGUgMjBtIGUgdXNhbmRvICpIYXphcmQgcmF0ZSogY29tbyAqa2V5IGZ1bmN0aW9uKiB1c2FuZG8gbyBhcmd1bWVudG8gYGtleWAgZSB0ZXJtbyBkZSBhanVzdGUgZG8gdGlwbyBjb3NzZW5vLgoKYGBge3J9CiMgS2V5IGZ1bmN0aW9uIC0gSGF6YXJkLXJhdGUgCmN1dGlhX3RhcF9hcmFwX2hyX2NvcyA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBkcygKICAgIHRydW5jYXRpb24gPSAyMCwKICAgIGtleSA9ICJociIKICAgICkKYGBgCgoKYGBge3J9CnBsb3QoY3V0aWFfdGFwX2FyYXBfaG4sIGJyZWFrcyA9IHNlcSgwLCAyMCwgMi41KSkKcGxvdChjdXRpYV90YXBfYXJhcF9obl9oZXJtLCBicmVha3MgPSBzZXEoMCwgMjAsIDIuNSkpCnBsb3QoY3V0aWFfdGFwX2FyYXBfaG5fY29zLCBicmVha3MgPSBzZXEoMCwgMjAsIDIuNSkpCnBsb3QoY3V0aWFfdGFwX2FyYXBfaHIsIGJyZWFrcyA9IHNlcSgwLCAyMCwgMi41KSkKcGxvdChjdXRpYV90YXBfYXJhcF9ocl9wb2x5LCBicmVha3MgPSBzZXEoMCwgMjAsIDIuNSkpCnBsb3QoY3V0aWFfdGFwX2FyYXBfaHJfY29zLCBicmVha3MgPSBzZXEoMCwgMjAsIDIuNSkpCmBgYAoKQWp1c3RhbmRvIHVtIG1vZGVsbyBhbyBkYWRvcyBkYXMgY3V0aWFzLCBjb25maWd1cmFuZG8gdW1hIGRpc3TDom5jaWEgbGltaXRlIGRlIDIwbSBlIHVzYW5kbyAqVW5pZm9ybSogY29tbyAqa2V5IGZ1bmN0aW9uKiBhIHPDqXJpYSBkZSBhanVzdGUgY29tIG8gYXJndW1lbnRvIGBhZGp1c3RtZW50YCBlZSBlc3BlY2lmaWNhbmRvIGEgb3JkZW0gY29tIG8gYXJndW1lbnRvIGBvcmRlcmAuCgpgYGB7cn0KY3V0aWFfdW5pZmNvcyA8LSBjdXRpYV90YXBfYXJhcCB8PiAKICBkcyh0cnVuY2F0aW9uID0gMjAsCiAgICAga2V5ID0gInVuaWYiLAogICAgIGFkanVzdG1lbnQgPSAiY29zIiwKICAgICBvcmRlciA9IGMoMSwgMikpCmBgYAoKQWp1c3RlICpIZXJtaXRlIHBvbGx5bm9taWFsKiB1c2Egb2QgY8OzZGlnbyBgImhlcm0iYCBlIHBvbGlub21pYWwgc2ltcGxlcyBgInBvbHkiYC4KClBvZGVtb3MgaW5jbHVpciBjb3ZhcmnDoXZlaXMgdXRpbGl6YW5kbyBvIGFyZ3VtZW50byBgZm9ybXVsYSA9IH4gLi4uYC4gQWJhaXhvLCBlc3TDoSBlc3BlY2lmaWNhZG8gdW0gbW9kZWxvICJIYXphcmQtcmF0ZSIgcGFyYSBvcyBkYWRvcyBkZSBjdXRpYSBxIHVlIGluY2x1aSBvIHRlbXBvIGRlIHNlbnNvIGNvbW8gY292YXJpw6F2ZWwgZSB1bWEgZGlzdMOibmNpYSBsaW1pdGUgZGUgMjBtLgoKYGBge3J9CmN1dGlhX2hyX3RpbWUgPC0gY3V0aWFfdGFwX2FyYXBfMTUgfD4gCiAgZHModHJ1bmNhdGlvbiA9IDIwLAogICAgIGtleSA9ICJociIsCiAgICAgZm9ybXVsYSA9IH4gY2Vuc2VfdGltZSkKYGBgCgpBZGljaW9uYW5kbyB1bWEgc2VndW5kYSBjb3ZhcmnDoXZlbDogdGFtYW5obyBkbyBncnVwby4KCmBgYHtyfQpjdXRpYV9ocl90aW1lX3NpemUgPC0gZHMoZGF0YSA9IGN1dGlhX3RhcF9hcmFwXzE1LAogICAgICAgICAgICAgICAgICAgICB0cnVuY2F0aW9uID0gMjAsCiAgICAgICAgICAgICAgICAgICAgIHRyYW5zZWN0ID0gImxpbmUiLAogICAgICAgICAgICAgICAgICAgICBrZXkgPSAiaHIiLAogICAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gfiBjZW5zZV90aW1lICsgc2l6ZSkKYGBgCgpgYGB7cn0KcGxvdChjdXRpYV9ocl90aW1lKQpwbG90KGN1dGlhX2hyX3RpbWVfc2l6ZSkKYGBgCgojIyBDaGVjYWdlbSBlIHNlbGXDp8OjbyBkZSBtb2RlbG9zCgpQb2RlbW9zIHVzYXIgYSBmdW7Dp8OjbyBgc3VtbWFyeWAgcGFyYSBvYnRlciBpbmZvcm1hw6fDtWVzIGltcG9ydGFudGVzIHNvYnJlIG8gbW9kZWxvLgoKYGBge3J9CnN1bW1hcnkoY3V0aWFfaG4pCmBgYAoKTyByZXN1bHRhZG8gIGluY2x1aSBkZXRhbGhlcyBzb2JyZSBvIGRhZG8gZSBhIGVzcGVjaWZpY2HDp8OjbyBkbyBtb2RlbG8sIGFzc2ltIGNvbW8gZG9zIGNvZWZpY2llbnRlcyAoJFxiZXRhX3tqfSQpIGUgc3VhIGluY2V0ZXphLCBhIG3DqWRpYSBkbyB2YWxvciBkZSBkZXRlY3RhYmlsaWRhZGUgZSBzdWEgaW5jZXJ0ZXphIGUgdW1hIGVzdGltYXRpdmEgZGEgYWJ1bmTDom5jaWEgbmEgw6FyZWEgY29iZXJ0YSBwZWxhIGFtb3N0cmFnZW0gKHNlbSBsZXZhciBlbSBjb25zaWRlcmHDp8OjbyBvIHRhbWFuaG8gZG9zIGFncnVwYW1lbnRvcywgb3UgYmFuZG9zKS4gCgojIyMgQm9uZGFkZSBkZSBhanVzdGUKClBhcmEgdmlzdWFsaXphciBxdcOjbyBiZW0gYSBmdW7Dp8OjbyBkZSBkZXRlY8Onw6NvIHNlIGFqdXN0YSBhb3MgZGFkb3MgcXVhbnRvIHRlbW9zIGFzIGRpc3TDom5jaWFzIGV4YXRhcyBwb2RlbW9zIHVzYXIgdW0gcGxvdCBkZSBxdWFudGlzIGVtcMOtcmljb3MgeCB0ZcOzcmljb3MgKFEtUSBwbG90KS4gRWxlIGNvbXBhcmEgYSBmdW7Dp8OjbyBkZSBkaXN0cmlidWnDp8OjbyBjdW11bGF0aXZhIChDREYpIGRvcyB2YWxvcmVzIGFqdXN0YWRvcyBkYSBmdW7Dp8OjbyBkZXRlY8Onw6NvIGEgZGlzdHJpYnVpw6fDo28gZW1ww61yaWNhIGRvcyBkYWRvcyAoRURGKS4gCgpUYW1iw6ltIHBvZGVtb3MgdXNhciBvIHRlc3RlIGRlIENyYW3DqXItdm9uIE1pc2VzIHBhcmEgdGVzdGFyIHNlIG9zIHBvbnRvcyBkYSBFREYgZSBkYSBDREYgdGVtIG9yaWdlbSBuYSBtZXNtYSBkaXN0cmlidWnDp8Ojby4gTyB0ZXN0ZSB1c2EgYSBzb21hIGRlIHRvZGFzIGFzIGRpc3TDom5jaWFzIGVudHJlIHVtIHBvbnRvIGUgYSBsaW5oYSB5ID0geCBwYXJhIGZvcm1hciBhIGVzdGF0w61zdGljYSBhIHNlciB0ZXN0YWRhLiBVbSByZXN1bHRhZG8gc2lnbmlmaWNhdGl2byBmb3JuZWNlIGV2aWTDqm5jaWEgY29udHJhIGEgaGlpcMOzdGVzZSBudWxhLCBzdWdlcmluZG8gcXVlIG8gbW9kZWxvIG7Do28gc2UgYWp1c3RhIGJlbSBhb3MgZGFkb3MuCgpgYGB7cn0KIyBhanVzdGFuZG8gdW0gbW9kZWxvIEhhbGYtbm9ybWFsCmN1dGlhX2huIDwtIGRzKGRhdGEgPSBjdXRpYV90YXBfYXJhcF8xNSwKICAgICAgICAgICAgICAgICB0cnVuY2F0aW9uID0gMjAsCiAgICAgICAgICAgICAgICAgdHJhbnNlY3QgPSAibGluZSIsCiAgICAgICAgICAgICAgICAga2V5ID0gImhuIiwgCiAgICAgICAgICAgICAgICAgYWRqdXN0bWVudCA9IE5VTEwpCgojIGNvbmR1emluZG8gbyB0ZXN0ZSBkZmUgYm9uZGFkZWRlIGFqdXN0ZSBkZSBDcmFtZXItdm9uIE1pc2VzCmdvZl9kcyhjdXRpYV9obikKCmdvZl9kcyhjdXRpYV9ocl90aW1lKQpgYGAKCk8gcmVzdXRsYWRvIGRvIHRlc3RlIGFwb250YSBxdWUgbyBtb2RlbG8gKkhhbGYtbm9ybWFsKiBkZXZlIHNlciBkZXNjYXJ0YWRvLgoKVGVzdGVzIGRlIGJvbmRhZGUgZGUgYWp1c3RlIGRlIGNoaS1xdWFkcmFkbyBzw6NvIGdlcmFkb3MgdXNhbmRvIGEgZnVuw6fDo28gYGdvZl9kc2AgcXVhbmRvIGFzIGRpc3TDom5jaWFzIGZvcm5lY2VpZGFzIGVzdMOjbyBjYXRlZ29yaXphZGFzLgoKIyMjIFNlbGXDp8OjbyBkZSBNb2RlbG9zCgpVbWEgdmV6IHF1ZSB0ZW1vcyB1bSBjb25qdW50byBkZSBtb2RlbG9zIHBsYXVzw612ZWlzLCBwb2RlbW9zIHV0aWxpemFyIG8gY2lydMOpcmlvZGUgaW5mb3JtYcOnw6NvZGUgQWthaWtlIChBSUMpIHBhcmEgc2VsZWNpb25hciBlbnRyZSBvcyBtb2RlbG9zIG8gcXVlIG1lbGhvciBzZSBhanVzdGEgYW9zIGRhZG9zIHV0aWxpemFuZG8gYSBmdW7Dp8OjbyBgc3VtbWFyaXplX2RzX21vZGVsc2AuCgpgYGB7cn0KIyBnZXJhbmRvIHVtYSB0YWJlbGEgZGUgc2VsZcOnw6NvIGRlIG1vZGVsb3MgdXNhbmRvIEFJQwpzdW1tYXJpemVfZHNfbW9kZWxzKGN1dGlhX2huLCBjdXRpYV9ocl90aW1lLCBjdXRpYV9ocl90aW1lX3NpemUpCmBgYAoKTyBtZWxob3IgbW9kZWxvIMOpIG8gSGF6YXJkLXJhdGUgY29tIHRlbXBvIGRlIHNlbnNvIGUgdGFtYW5obyBkbyBncnVwbyBjb21vIGNvdmFyacOhdmVpcy4KCiMjIEVzdGltYW5kbyBhIGFidW5kw6JuY2lhIGUgYSB2YXJpw6JuY2lhCgojIyMgRXN0aW1hbmRvIGFidW5kw6JuY2lhIGUgdmFyacOibmNpYSBubyBSCgpQYXJhIG9idGVyIGEgYWJ1bmTDom5jaWEgbmEgcmVnacOjbyBkZSBlc3R1ZG8sIHByaW1laXJvIGNhbGN1bGFtb3MgYSBhYnVuZMOibmNpYSBuYSDDoXJlYSBhbW9zdHJhZGEgcGFyYSBvYnRlciAkTl9jJCBlIGVtIHNlZ3VpZGEgZXNjYWxvbmFtb3MgZXNzZSB2YWxvciBwYXJhIHRvZGEgYSDDoXJlYSBkZSBlc3R1ZG8gbXVsdGlwbGljYW5kbyAkTl9jJCBwZWxhIHJhesOjbyBlbnRyZSBhIMOhcmVhIGFtb3N0cmFkYSBlIGEgw6FyZWEgZGEgcmVnacOjby4gUGFyYSBlc3RpbWFyIGEgYWJ1bmTDom5jaWEgbmEgw6FyZWEgYW1vc3RyYWRhLCB1dGlsaXphbW9zIGFzIGVzdGltYXRpdmFzIGRlIHByb2JhYmlsaWRhZGUgZGUgZGV0ZWPDp8OjbyBubyBlc3RpbWFkb3IgZGUgSG9ydml0ei1UaG9tcHNvbi4KClF1YW5kbyBmb3JuZWNlbW9zIG9zIGRhZG9zIG5vIGZvcm1hdG8gY29ycmV0byAoImZsYXRmaWxlIikgYGRzYCBpcsOhIGF1dG9tYXRpY2FtZW50ZSBjYWxjdWxhciBhcyBlc3RpbWF0aXZhcyBkZSBhYnVuZMOibmNpYSBiYXNlYWRvIG5hcyBpbmZvcm1hw6fDtWVzIGRlIGFtb3N0cmFnZW0gcHJlc2VudGEgbm9zIGRhZG9zLgoKYGBge3J9CnN1bW1hcnkoY3V0aWFfaG4pCmBgYAoKMS4gU3VtbWFyeSBzdGF0aXN0aWNzOiBmb3JuZWNlIGFzIMOhcmVhcywgYcWVZWEgZGUgYW1vc3RyYWdlbSwgZXNmb3LDp28sIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcywgbsO6bWVybyBkZSB0cmFuc2VjdG9zLCB0YXhhIGRlIGVuY29udHJvLCBzZXVzIGVycm9zIHBhZHLDtWVzIGUgY29lZmljaWVudGVzIGRlIHZhcmlhw6fDo28gcGFyYSBjYWRhIGVzdHJhdG87CgoyLiBBYnVuZGFuY2U6IGZvcm5lY2UgZXN0aW1hdGl2YXMsIGVycm9zIHBhZHLDtWVzLCBjb2VmaWNpZW50ZXNkZSB2YXJpYcOnw6NvLCBpbnRlcnZhbG9zIGRlIGNvbmZpYW7Dp2EgaW5mZXJpb3IgZSBzdXBlcmlvciwgZ3JhdXMgZGUgbGliZXJkYWRlIHBhcmEgYSBlc3RpbWF0aXZhIGRlIGFidW5kw6JuY2lhIGRlIGNhZGEgZXN0cmF0bzsKCjMuIERlbnNpZGFkZTogbGlzdGEgYXMgbWVzbWFzIGVzdGF0w61zdGljYXMgZGUgQWJ1bmRhbmNlLCBzw7MgcXVlIHBhcmEgZGVuc2lkYWRlLgoK